package com.bzm.config.im;

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.bzm.SpringBeanUtil;
import com.bzm.common.entity.HttpCode;
import com.bzm.common.entity.JsonResult;
import com.bzm.common.enums.plugins.ImChatMsgTypeEnum;
import com.bzm.config.BzmGlobalConfig;
import com.bzm.pojo.plugins.im.ImChatMsg;
import com.bzm.service.plugins.BzmImCommonService;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;

/**
 * @Description:处理消息的handler
 * 				TextWebSocketFrame： 在netty中，是用于为websocket专门处理文本的对象，frame是消息的载体
 * SimpleChannelInboundHandler：	对于请求来讲 ，相当于 【入站，入境】
 * @author hemiao
 * @time:2020年5月20日 上午9:07:16
 */
@Component
@Slf4j
public class NettyWsChannelInboundHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{
	
	/**
	 * 用于记录和管理所有客户端的channle
	 */
	//public static ChannelGroup users = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
	
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
		HttpCode httpCode = HttpCode.PARAM_VERIFICATION;
		// 获得   channel
		Channel currentChannel = ctx.channel();
		try {
			BzmImCommonService bzmImCommonService = (BzmImCommonService)SpringBeanUtil.getBean("bzmImCommonServiceImpl");
			
			BzmGlobalConfig bzmGlobalConfig = (BzmGlobalConfig)SpringBeanUtil.getBean("bzmGlobalConfig");
			try {
				String serverName = InetAddress.getLocalHost().getHostAddress();
				 String hostName = InetAddress.getLocalHost().getHostName();
				 System.out.println(serverName + hostName);
			} catch (UnknownHostException e) {
				
			}
			
			// 当前服务器  ip 和 端口一致
			String currentLocalAddress = bzmGlobalConfig.getIP()+bzmGlobalConfig.getPort();
			
		    // 判断接收消息用户是否在本服务端
		    
		    // 如果为NULL则接收消息的用户不在本服务端，需要push消息给全局
			
		    	
			// 获取客户端传输过来的消息
			String msgObjJson = msg.text();
			//System.out.println(" msgObjJson ="+msgObjJson);
			// 解析消息
			ImChatMsg imChatMsg = BzmImChatUtils.beforeMsgAuth(msgObjJson);
			imChatMsg.setImLocalAddress(currentLocalAddress);
			String sendId = imChatMsg.getSendId();
			Integer msgType = imChatMsg.getMsgType();
			if(msgType.equals(ImChatMsgTypeEnum.CONNECT.getCode())) {
				// 将用户 丢到 
				bzmImCommonService.addImUserAddress(imChatMsg);
				// 用户连接
				UserChannelRel.put(sendId, currentChannel);
			}else {
				// 处理消息
				bzmImCommonService.sendMsg(imChatMsg);
			}
			// 回复消息
			imChatMsg.setMsgCallCack(true);
			currentChannel.writeAndFlush(
					new TextWebSocketFrame(
							JSON.toJSONString(new JsonResult<ImChatMsg>(imChatMsg, HttpCode.SUCCESS),SerializerFeature.WriteMapNullValue)));
		} catch (Exception e) {
			e.printStackTrace();
			httpCode.setMsg(e.getMessage());
			currentChannel.writeAndFlush(
					new TextWebSocketFrame(
							JSON.toJSONString(new JsonResult<String>(null, httpCode),SerializerFeature.WriteMapNullValue)));
		}
	}
	
	

	@Override
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		Channel channel = ctx.channel();
		String channelId = channel.id().asLongText();
		// 当客户端连接服务端之后（打开连接）
		// 获取客户端的channle，并且放到ChannelGroup中去进行管理
		//users.add(channel);
		//UserChannelRel.put(channelId, channel);
		//log.info(" netty 获得连接.....id="+channelId);
		log.info(" netty 获得连接.....	channelId = " + channelId);
	}

	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		Channel channel = ctx.channel();
		String userId = UserChannelRel.removeChannelId(channel,"处理程序删除-handlerRemoved:");
		if(StringUtils.isNotBlank(userId)) {
			BzmImCommonService bzmImCommonService = (BzmImCommonService)SpringBeanUtil.getBean("bzmImCommonServiceImpl");
			bzmImCommonService.offLineMsg(userId);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		Channel channel = ctx.channel();
		String userId = UserChannelRel.removeChannelId(channel,"捕捉到未知-exceptionCaught:");
		if(StringUtils.isNotBlank(userId)) {
			BzmImCommonService bzmImCommonService = (BzmImCommonService)SpringBeanUtil.getBean("bzmImCommonServiceImpl");
			bzmImCommonService.offLineMsg(userId);
		}
	}

}
